
#include "DllLoader.h"

#include "Common/Errors.h"
#include "Runtime.Low/Services.h"

using namespace std;
using namespace ttg;
using namespace ttg::structures;
using namespace ttg::services;
using namespace ttg_internal::services;

//-----------------
//--- DllLoader ---
//-----------------

DllLoader *DllLoader::ref = NULL;

void DllLoader::startUnSafe(vector<Service *> &deps, const char *params)
{
	this->dlls = Dictionary<DllLoaderRec>::create(50);
}

void DllLoader::stopUnSafe()
{
	if (dlls != NULL)
	{
		list<DllLoaderRec *> records = dlls->toList();
		list<DllLoaderRec *>::iterator it = records.begin();
		while (it != records.end())
		{
			if (*it != NULL)
			{
				FreeLibrary((*it)->getRef());
				delete (*it);
			}
			it++;
		}
		delete dlls;
		dlls = NULL;
	}
}

DllLoader::DllLoader()
	:Service("DllLoader", "Logger", false)
{
	this->dlls = NULL;
	makeRegistration();
}

void DllLoader::load(const char *dllname, const char *funcname, FARPROC &funcaddr)
{
	DllLoaderRec *rec = dlls->get(dllname);
	if (rec == NULL)
	{
		HMODULE module = LoadLibraryA(dllname);
		if (module == NULL)
			throw Error(Error::FATAL, "DllLoader", "load", "Cannot load dll", dllname);
		rec = new DllLoaderRec(dllname, module);
		dlls->add(rec);
	}
	if (!rec->isLoaded(funcname))
	{
		FARPROC temp = GetProcAddress(rec->getRef(), funcname);
		if (temp == NULL)
			throw Error(Error::FATAL, "DllLoader", "load", "Cannot load function", funcname);
		funcaddr = temp;
		rec->add(funcname);
	}
}
